using AutoMapper;
using MongoDB.Driver;
using Sustainalytics.CDDB.DataConnector;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.ClientDW.Synchronization.SyncHbaseData.CorporateDataLogic;
using Sustainalytics.ClientDW.Synchronization.SyncHbaseData.CorporateDetailsLogic;
using Sustainalytics.SharedEntities.Corporate;
using Sustainalytics.Synchronization.Interface;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using CompanyProfileResearchState = Sustainalytics.BusinessResearchProductStates.Entities.ResearchState.CompanyProfileResearchState;

namespace Sustainalytics.ClientDW.Synchronization.SyncHbaseData
{
    public class CorporateDataSync
    {
        private readonly CorporateDatabaseQuery hbaseQuery;
        private readonly SyncCommand syncCommand;
        private readonly ILogger logger;

        public CorporateDataSync(
            CorporateDatabaseQuery hbaseQuery,
            SyncCommand syncCommand,
            ILogger logger)
        {
            this.hbaseQuery = hbaseQuery;
            this.syncCommand = syncCommand;
            this.logger = logger;
        }

        public async Task Start(HashSet<string> identifierTypesIds)
        {
            logger.Log($"Start at {DateTime.UtcNow} ");

            var stopWatch = Stopwatch.StartNew();

            await RecreateCollections();

            var corporateDetails = hbaseQuery.Get(CorporateDetailsDataBaseQuery.Get);

            var corporateData = await RecreateFromCorporateDetails<CorporateData>(corporateDetails, CorporateDataCommand.RecreateIndexes);
            await RecreateFromCorporateDetails<CompanyProfileResearchState>(corporateDetails);
            await RecreateFromCorporateDetails<FinancialData>(corporateDetails);

            //here company search collection is dropped
            var corporateDataWithMainSecurity = corporateData.Where(cd => cd.MainIdentifiers.SecurityId?.Length > 2).ToDictionary(cd => cd.Id);

            stopWatch.Stop();
            logger.Log($"COMPLETED at {DateTime.UtcNow} duration {stopWatch.Elapsed} ");
        }

        public async Task RecreateCollections()
        {
            await RecreateCollection(cddb => cddb.ListCountries());
            await RecreateCollection(cddb => cddb.ListCorporateGovernanceRegions());
            await RecreateCollection(cddb => cddb.GetPeerGroups());
            await RecreateCollection(cddb => cddb.ListRegions());
        }

        public async Task RecreateCollection<T>(Func<CorporateDataRepository, IEnumerable<T>> getEntities)
        {
            var entities = hbaseQuery.Get(getEntities);

            await syncCommand.ExecuteAsync(entities);
        }

        public async Task<IEnumerable<T>> RecreateFromCorporateDetails<T>(
            IEnumerable<CorporateDetails> corporateDetails,
            Func<IMongoCollection<T>, Task> recreateIndexes = null)
        {
            var entities = corporateDetails.Select(Mapper.Map<T>);

            await syncCommand.ExecuteAsync(entities, recreateIndexes);

            return entities;
        }
    }
}
